import { ELType, GroupType } from "./ELType";

export default class ELNode {
    id: string;
    type: ELType;
    groupType: GroupType;
    aliasId: string;
    name: string;
    data: string;
    tag: string;
    nodeId: string;
    child: ELNode[];
    comingEdgeText: string; //指向该节点边的标签
    elString: string | undefined;

    properties: Record<string, unknown> | undefined

    //group专用
    startNode: ELNode;
    breakNode: ELNode;
    exceptionNode: ELNode;
    startNum: number;

    constructor(id: string = "") {
        if (id) this.id = id
        this.child = []
    }

    public addChild(elNode: ELNode) {
        if (!this.child) this.child = []
        this.child.push(elNode);
    }

    private assert(condition: boolean, msg: string = "") {
        if (!condition) throw new Error(msg);
    }

    public getElString() {
        if (this.type === ELType.ID) return this.nodeId;
        if (this.elString) return this.elString;

        const type = this.type;
        const children = this.child || [];
        const joins = children.map(item => item.getElString()).join(",");
        switch (type) {
            case ELType.IF:
                if (children.length === 1) return `IF(${joins})`;
                return `IF(${joins})`;
            case ELType.GROUP:
                // 配置节点解析
                if (this.groupType === GroupType.CONFIG) {
                    const idStr = this.aliasId ? `.id(${this.aliasId})` : ``
                    const tagStr = this.tag ? `.tag(${this.tag})` : ``
                    const ignoreStr = this.properties?.ignoreError ? `.ignoreError(true)` : ``;
                    const anyStr = this.properties?.any ? `any(true)` : ``;
                    const mustStr = this.properties?.must ? `must(${this.properties?.must})` : ``;

                    return `${joins}${ignoreStr}${anyStr}${mustStr}${idStr}${tagStr}`
                }

                //与或非表达式解析
                if (this.groupType === GroupType.LOGIC) {
                    return ELNode.formatterNode(this.child[0]);
                }
                const name = this.groupType;
                // 捕获异常表达式解析
                if (this.groupType === GroupType.CATCH) {
                    const exceptionStr = this.exceptionNode.getElString();
                    return `${name}(${joins}).DO(${exceptionStr})`
                }
                // 循环节点解析
                const breakStr = !!this.breakNode ? `.BREAK(${this.breakNode.nodeId})` : ""
                const startStr = (this.startNode?.nodeId) ? this.startNode.getElString() : this.startNum;
                if (children.length === 1) return `${name}(${startStr}).DO(${joins})${breakStr}`;
                else return `${name}(${startStr}).DO(WHEN(${joins}))${breakStr}`;
            case ELType.SWITCH:
                return `SWITCH(${this.nodeId}).to(${joins})`;
            default:
                if (children.length === 1) return joins;
                return `${this.type}(${joins})`
        }
    }

    /**
     * 将正常解析的节点转化为与或非节点
     * @returns ELNODE
     */
    public toLogicNode(): ELNode {
        const node: ELNode = new ELNode()
        node.elString = ELNode.formatterNode(this)

        return node;
    }

    private static formatterNode(node: ELNode, option?: ELType): string {

        if (node.type === ELType.ID) return node.nodeId;
        if (node.type === ELType.WHEN) {
            const joins = node.child.map(item => this.formatterNode(item)).join(",");
            return `${option}(${joins})`
        }

        if (node.type === ELType.THEN) {
            let res = ""
            node.child.forEach((item, index) => {
                if (item.type === ELType.WHEN || item.type === ELType.ID) {
                    res += this.formatterNode(item, node.child[index + 1]?.type)
                    return
                }
                if (item.type === ELType.NOT) {
                    res = `NOT(${res})`
                }
            })
            return res;
        }
        return ""
    }
}